package com.wei.czz.framework.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wei.czz.common.constant.Constant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.CopyUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.admin.dept.DeptFormVo;
import com.wei.czz.framework.admin.dao.DeptDao;
import com.wei.czz.framework.admin.entity.DeptEntity;
import com.wei.czz.framework.admin.service.DeptService;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2022-08-16 21:18:56
 * className: DeptServiceImpl 系统部门操作服务接口实现类
 * version: 1.0
 * description:
 */
@Service("deptService")
@AllArgsConstructor
public class DeptServiceImpl extends ServiceImpl<DeptDao, DeptEntity> implements DeptService {

    private static final Logger log = LoggerFactory.getLogger(DeptServiceImpl.class);

    @Override
    public void saveOrEdit(DeptEntity dept) {
        Long id = dept.getId();
        if (Objects.isNull(id)) {

            int count = baseMapper.insert(dept);
            log.info("插入部门完成。count={}", count);
        } else {

            int count = baseMapper.updateById(dept);
            log.info("修改部门完成。count={}", count);
        }
    }

    @Transactional
    @Override
    public void batchSave(List<DeptEntity> deptList) {
        boolean bool = this.saveBatch(deptList);
        log.info("批量保存部门完成。bool={}", bool);
    }

    @Override
    public PageDto<DeptEntity> getPageList(boolean requestMode, List<Long> idList, DeptFormVo deptFormVo) {
        // 构造分页对象
        Page<DeptEntity> page = new Page<>(deptFormVo.getPage(), deptFormVo.getLimit());

        Long parentId = Optional.ofNullable(idList).filter(list -> list.size() == 1).map(list -> list.get(0))
                .orElse(null);

        LambdaQueryWrapper<DeptEntity> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 匹配 父级部门主键和删除状态 字段
        deptLambdaQueryWrapper.in(requestMode && Objects.isNull(parentId), DeptEntity::getId, idList)
                .eq(requestMode && Objects.nonNull(parentId), DeptEntity::getParentId, parentId)
                .like(!requestMode, DeptEntity::getName, deptFormVo.getWord())
                .eq(Objects.nonNull(deptFormVo.getBusinessType()), DeptEntity::getBusinessType, deptFormVo.getBusinessType())
                .eq(Objects.nonNull(deptFormVo.getStatus()), DeptEntity::getStatus, deptFormVo.getStatus())
                .eq(DeptEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 设置排序方式
        deptLambdaQueryWrapper.orderByAsc(DeptEntity::getSort, DeptEntity::getCreateTime);

        // 查询数据库系统部门表，分页获取数据
        this.page(page, deptLambdaQueryWrapper);
        log.info("分页查询部门完成。list.size={} totalNum={}", page.getRecords().size(), page.getTotal());

        List<DeptEntity> deptList = page.getRecords();

        if (!deptList.isEmpty() && requestMode) {
            // 批量查询子部门数据列表
            List<DeptEntity> childrenDeptList = this.batchQueryDeptList(deptList, deptFormVo);
            deptList.addAll(childrenDeptList);
        }

        return new PageDto<>(page);
    }

    @Override
    public List<DeptEntity> getDeptList() {
        LambdaQueryWrapper<DeptEntity> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 匹配 删除状态 字段
        deptLambdaQueryWrapper.eq(DeptEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询数据库系统部门表，获取部门数据列表
        List<DeptEntity> deptList = baseMapper.selectList(deptLambdaQueryWrapper);
        log.info("查询所有未删除部门完成。size={}", deptList.size());
        return deptList;
    }

    @Override
    public DeptEntity get(Long id) {
        // 查询
        DeptEntity dept = baseMapper.selectById(id);
        if (Objects.isNull(dept)) {
            log.info("部门不存在。deptId={}", id);
            throw new CzzException(ResultEnum.NOT_FOUND.getCode(), "部门不存在，请确认。");
        }
        if (CommonEnum.ONE.getValue().equals(dept.getDeleteStatus())) {
            log.info("部门已删除。deptId={}", id);
            throw new CzzException(ResultEnum.NOT_FOUND.getCode(), "部门不存在，请确认。");
        }
        return dept;
    }

    @Override
    public List<Long> getChildrenIdList(Long id) {
        DeptEntity dept = this.get(id);
        // 构造部门路径
        String deptPath = dept.getParentPath() + id + Constant.SPLIT;
        // 查询子部门主键
        List<Long> deptIdList = baseMapper.selectChildrenIdList(deptPath, CommonEnum.ZERO.getValue());
        log.info("查询子、子孙部门主键完成。id={} size={}", id, deptIdList.size());
        return deptIdList;
    }

    @Override
    public List<Long> getDirectChildrenIdList(Long id) {
        List<Long> deptIdList = baseMapper.selectDirectChildrenIdList(id, CommonEnum.ZERO.getValue());
        log.info("查询直接子部门主键完成。id={} size={}", id, deptIdList.size());
        return deptIdList;
    }

    @Override
    public List<DeptEntity> getChildrenList(String parentPath) {
        // 查询数据库系统部门表，获取部门数据
        List<DeptEntity> deptList = baseMapper.selectChildrenList(parentPath, CommonEnum.ZERO.getValue());
        log.info("查询子、子孙部门完成。parentPath={} size={}", parentPath, deptList.size());
        return deptList;
    }

    @Override
    public List<Long> findParentIdList(Long id) {
        DeptEntity dept = this.get(id);
        return this.findParentIdList(dept);
    }

    @Override
    public List<Long> findParentIdList(DeptEntity dept) {
        if (Objects.isNull(dept)) {
            return Collections.emptyList();
        }
        String deptPath = dept.getParentPath();
        List<Long> parentIdList = Stream.of(deptPath.split(Constant.SPLIT))
                .map(Long::valueOf)
                .filter(_id -> !CommonEnum.ZERO.getLongValue().equals(_id))
                .collect(Collectors.toList());
        log.info("获取父级部门主键完成。parentIdList={}", parentIdList);
        return parentIdList;
    }

    @Override
    public List<Long> findParentIdList(List<Long> idList) {
        /*

         */
        List<DeptEntity> deptList = this.getList(idList);

        return deptList.stream()
                .flatMap(dept -> this.findParentIdList(dept).stream())
                .distinct()
                .collect(Collectors.toList());
    }

    @Override
    public List<DeptEntity> getList(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            log.info("批量获取部门，传入部门主键列表为空");
            return Collections.emptyList();
        }
        LambdaQueryWrapper<DeptEntity> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptLambdaQueryWrapper.in(DeptEntity::getId, idList)
                .eq(DeptEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<DeptEntity> deptList = baseMapper.selectList(deptLambdaQueryWrapper);
        log.info("批量查询部门完成。params.size={} size={}", idList.size(), deptList.size());
        return deptList;
    }

    @Override
    public List<DeptEntity> findList(List<Long> idList) {
        // 查询
        List<DeptEntity> deptList = this.getList(idList);
        // 查询子、子孙部门
        List<DeptEntity> childrenList = this.batchQueryDeptList(deptList, new DeptFormVo());
        deptList.addAll(childrenList);
        return deptList;
    }

    @Override
    public List<DeptEntity> findDirectChildrenList(Long parentId) {
        LambdaQueryWrapper<DeptEntity> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptLambdaQueryWrapper.eq(DeptEntity::getParentId, parentId)
                .eq(DeptEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<DeptEntity> deptList = baseMapper.selectList(deptLambdaQueryWrapper);
        log.info("查询直接子部门完成。parentId={} size={}", parentId, deptList.size());
        return deptList;
    }

    @Override
    public List<DeptEntity> findListByName(List<String> nameList) {
        if (CollectionUtils.isEmpty(nameList)) {
            log.info("获取部门列表，传递的部门名称列表为空");
            return Collections.emptyList();
        }

        LambdaQueryWrapper<DeptEntity> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptLambdaQueryWrapper.in(DeptEntity::getName, nameList)
                .eq(DeptEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<DeptEntity> deptList = baseMapper.selectList(deptLambdaQueryWrapper);
        log.info("根据名称查询部门完成。nameList.size={} list.size={}", nameList.size(), deptList.size());
        return deptList;
    }

    @Override
    public Integer getNextSort(Long deptId) {
        Integer maxSort = baseMapper.selectMaxSort(deptId, CommonEnum.ZERO.getValue());
        log.info("查询结果：maxSort={}", maxSort);
        if (maxSort == null) {
            maxSort = 0;
        }
        return maxSort + 1;
    }

    @Override
    public <R> Map<R, String> getDeptNameMap(Collection<Long> deptIdCollection, @NonNull Function<Long, R> function) {
        if (CollectionUtils.isEmpty(deptIdCollection)) {
            log.info("获取部门名称映射，传入的部门主键集合为空");
            return Collections.emptyMap();
        }
        LambdaQueryWrapper<DeptEntity> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询 部门主键和部门名称 字段
        deptLambdaQueryWrapper.select(DeptEntity::getId, DeptEntity::getName);
        // 匹配 部门主键和删除状态 字段
        deptLambdaQueryWrapper.in(DeptEntity::getId, deptIdCollection)
                .eq(DeptEntity::getDeleteStatus, CommonEnum.ZERO.getValue());

        // 查询数据库系统部门表，获取部门数据
        List<DeptEntity> deptList = baseMapper.selectList(deptLambdaQueryWrapper);
        log.info("查询部门简单数据完成。param.size={} list.size={}", deptIdCollection.size(), deptList.size());
        if (deptList.isEmpty()) {
            return Collections.emptyMap();
        }
        // list 转 map
        return CopyUtils.listToMap(deptList, function.compose(DeptEntity::getId), DeptEntity::getName);
    }

    @Transactional
    @Override
    public void batchUpdate(List<DeptEntity> deptList) {
        // 批量更新
        boolean bool = this.updateBatchById(deptList);
        log.info("批量修改部门完成。bool={}", bool);
    }

    @Override
    public void delete(List<Long> deptIdCollection) {
        // 获取操作用户主键
        Long optUserId = SecurityUtils.getUserId();

        LambdaUpdateWrapper<DeptEntity> deptLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置 删除状态、更新时间和操作更新的用户 字段值
        deptLambdaUpdateWrapper.set(DeptEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(DeptEntity::getUpdateTime, new Date())
                .set(DeptEntity::getUpdateUserId, optUserId);
        // 匹配 部门主键、删除状态 字段
        deptLambdaUpdateWrapper.in(DeptEntity::getId, deptIdCollection)
                .eq(DeptEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 操作数据库部门表，批量删除部门数据
        int count = baseMapper.update(null, deptLambdaUpdateWrapper);
        log.info("批量删除部门完成。count={}", count);
    }

    /**
     * 批量查询子部门数据列表
     * 查询结果填充到’父级部门数据列表‘中
     * @param deptList   父级部门数据列表
     * @param deptFormVo 参数对象
     */
    private List<DeptEntity> batchQueryDeptList(List<DeptEntity> deptList, DeptFormVo deptFormVo) {
        LambdaQueryWrapper<DeptEntity> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        deptLambdaQueryWrapper.and(_deptLambdaQueryWrapper -> {
            for (DeptEntity dept : deptList) {
                String deptPath = dept.getParentPath() + dept.getId() + Constant.SPLIT;
                _deptLambdaQueryWrapper.likeRight(DeptEntity::getParentPath, deptPath)
                        .or();
            }
        });
        deptLambdaQueryWrapper.eq(
                    Objects.nonNull(deptFormVo.getBusinessType()), DeptEntity::getBusinessType, deptFormVo.getBusinessType()
                )
                .eq(Objects.nonNull(deptFormVo.getStatus()), DeptEntity::getStatus, deptFormVo.getStatus())
                .eq(DeptEntity::getDeleteStatus, deptFormVo.getDeleteStatus());
        // 查询
        List<DeptEntity> childrenDeptList = baseMapper.selectList(deptLambdaQueryWrapper);
        log.info("查询子、子孙部门完成。size={}", childrenDeptList.size());
        return childrenDeptList;
    }

}